var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var util = require('util');

var Port = new Schema({
	name : String,
	device : {
		type : Schema.ObjectId,
		ref : 'Device'
	},
	sysId : {
		type : String,
		unique : true
	},
	type : {
		type : String,
		enum : [ 'Boolean', 'Number' ]
	},
	direction : {
		type : String,
		enum : [ 'Input', 'Output' ]
	},
	inputs : [ {
		type : Schema.ObjectId,
		ref : 'Port'
	} ],
	relation : String,
	smoothing : {
		type : Number,
		'default' : 0
	},
	description : String,
	value : String,
	inputs : [ {
		type : Schema.ObjectId,
		ref : 'Port'
	} ]
});

/**
 * Compound unique index of parent device and remote port name
 * 
 * @mamberOf Port
 * @type index
 * @static
 */
Port.index({
	device : 1,
	name : 1
}, {
	unique : true
});

Port.pre('remove', function(next) {
	log.debug("Remove pre");
	var self = this;

	model.Device.findOne({
		_id : self.device
	}, function(e, device) {
		log.debug("Number of Ports " + device.ports.length);

		for ( var p = 0; p < device.ports.length; p++) {
			log.debug('Port: ' + device.ports[p] + ", my ID: " + self._id);
			if (device.ports[p].toString() == self._id.toString()) {
				log.debug("Match");
				device.ports.splice(p, 1);
				log.debug("Done?");
				device.save(next);
				break;
			}
		}
	});
});

Port.methods.calculate = function() {
	var self = this;
	if (this.direction == 'Output') {
		var inputs = {};
		this.inputs.forEach(function(input) {
			inputs[input.sysId] = input.value;
		});

		log.debug(util.inspect(inputs));

		var output = null;
		log.debug("Relation: " + this.relation);
		eval(this.relation);

		this.value = output || this.value;
		log.debug("New " + this.sysId + " Value: " + this.value);

		this.save(function(e) {
			log.debug("Emitting 'port_update'");
			tasks.emit('port_update', self._id, self.value);
		});
	}
};

model.Port = mongoose.model('Port', Port);

tasks.on('port_update', function(id, value) {
	model.Port.find({
		inputs : id,
		direction : 'Output'
	}).populate('inputs').populate('device').run(function(e, ports) {
		ports.forEach(function(port) {
			log.debug("Recalculating Port " + port._id);
			port.calculate();
		});
	});
});
